#!/usr/bin/python2.5

import datetime
import operator
import StringIO
from xml.dom import minidom
import BeautifulSoup
from controllers import geocode
from controllers import query
from google.appengine.api import urlfetch
from google.appengine.ext import webapp
import wsgiref.handlers


def MungeHTML(page):
  tree = BeautifulSoup.BeautifulSoup(page)
  scripts = tree.findAll("script")
  incidents=[]
  for script in scripts:
    if not len(script.contents):
      continue
    if not script.contents[0].startswith('fireStatuses[fireStatuses.length]'):
      continue
    body = script.contents[0][37:-2]
    incidents.append(ParseValues(body))
  return incidents


def ParseValues(remaining):
    incident={}
    while remaining:
      # first quote
      _, _, remaining = remaining.partition("'")
      # key name
      k, _, remaining = remaining.partition("'")
      # closing quote and colon
      _, _, remaining = remaining.partition(":")
      # value openining quote
      _, _, remaining = remaining.partition("'")
      # key value
      v, _, remaining = remaining.partition("'")
      _, _, remaining = remaining.partition(",")
      incident[k.strip()] = v.strip()
    return incident

# From http://www.cfa.vic.gov.au/incidents/definitions/size.htm
CFASizes = [
    (0.5, 'SPOT'),
    (5, 'SMALL'),
    (50, 'MEDIUM'),
]

def GenRSS(incidents):
  """Turns a list of incident dictionaries into an RSS feed."""
  for incident in incidents:
    incident['datetime'] = datetime.datetime.strptime(incident['lastPirDate'],
        '%d/%m/%y %I:%M:%S %p').strftime('%a, %d %b %Y %H:%M:%S')
    incident['starttime'] = datetime.datetime.strptime(
        incident['incidentOriginDate'],
        '%d/%m/%y %I:%M:%S %p').strftime('%a, %d %b %Y %H:%M:%S')
  incidents.sort(key=lambda x: operator.getitem(x, 'datetime'), reverse=True)

  impl = minidom.getDOMImplementation()
  doc = impl.createDocument(None, 'rss', None)
  rss = doc.childNodes[0]
  rss.setAttribute('xmlns:georss', 'http://www.georss.org/georss')
  rss.setAttribute('xmlns:atom', 'http://www.w3.org/2005/Atom')
  rss.setAttribute('version', '2.0')
  rss.setAttribute('xmlns:dc', 'http://purl.org/dc/elements/1.1/')
  rss.setAttribute('xmlns:rdf', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#')
  rss.setAttribute('xmlns:taxo', 'http://purl.org/rss/1.0/modules/taxonomy/')
  channel = rss.appendChild(doc.createElement('channel'))
  channel.appendChild(doc.createElement('title')).appendChild(
      doc.createTextNode('Vic CFA Fire Information'))
  description = channel.appendChild(doc.createElement('description'))
  description.appendChild(doc.createTextNode(
      'This is an RSS view of the data from the page '
      'http://osom.cfa.vic.gov.au/public/osom/osom_wrapper.html'))
  for incident in incidents:
    item = channel.appendChild(doc.createElement('item'))
    if incident['name'].strip():
      if incident['territory'] == 'CFA':
        title = '%s, %s' % (incident['name'], incident['incidentLocation'])
      else:
        # DSE has useful name values
        title = incident['name']
    else:
      title = incident['incidentLocation']
    item.appendChild(doc.createElement('title')
                    ).appendChild(
                        doc.createTextNode(title))

    item.appendChild(doc.createElement('pubDate')
                    ).appendChild(doc.createTextNode(incident['datetime']))

    size = incident['incidentSize']
    if size[0].isdigit():
      if size.endswith('HA.'):
        size = size[:-4]  # strip off ' HA.'
        size = float(size)
        for maxSize, name in CFASizes:
          if size < maxSize:
            level = name
            break
        else:
          level = 'LARGE'
      else:
        level = 'UNKNOWN'
    else:
      level = size
    incident['level'] = level


    if not incident['name'].strip():
      incident['name'] = incident['incidentLocation']
    desc = ('Name: %(name)s<br/>'
            'Location: %(incidentLocation)s<br/>'
            'Type: %(incidentType)s<br/>'
            'Last Update: %(datetime)s<br/>'
            'Start Time: %(starttime)s<br/>'
            'Status: %(status)s<br/>Region: %(territory)s %(region)s<br/>'
            'Size: %(incidentSize)s<br/>'
            'Level: %(level)s<br/><br/>'
            'Information from Victorian CFA. See '
            'http://www.cfa.vic.gov.au for more.'%(incident))
    item.appendChild(doc.createElement('description')
                    ).appendChild(doc.createCDATASection(desc.encode('utf-8')))
    if incident['latitude']:
      point = item.appendChild(doc.createElement('georss:point'))
      point.appendChild(
          doc.createTextNode('%s %s' % (incident['latitude'],
                                        incident['longitude'])))
    item.appendChild(doc.createElement('georss:featuretypetag')
                    ).appendChild(doc.createTextNode('point'))
  output_rss = StringIO.StringIO()
  doc.writexml(output_rss)
  return output_rss.getvalue()


class FetchRSS(webapp.RequestHandler):
  """Fetch the CFA webpage, munge into RSS, store the RSS."""

  def get(self):
    """GET handler."""
    result = urlfetch.fetch(
        'http://osom.cfa.vic.gov.au/public/osom/osom_wrapper.html')
    if result.status_code == 200:
      incidents = MungeHTML(result.content)
      rss = GenRSS(incidents).encode('utf-8')
      query.PutData('viccfa', rss)

      self.response.headers.add_header('Cache-control',
                                       'no-cache, must-revalidate')
      self.response.headers['Content-Type'] = 'text/plain'
      self.response.out.write(rss)

def main():
  app = webapp.WSGIApplication([
      ('/query/viccfa', FetchRSS),
      ], debug=True)
  wsgiref.handlers.CGIHandler().run(app)

if __name__ == '__main__':
  main()
